/**
 * 最近更新: 2018-10-12
 * 作者: wangyr
 * 功能: vue 自定义指令
 * 用法: 在元素上绑定 v-focus、v-time...
 * 详细参数介绍: https://cn.vuejs.org/v2/guide/custom-directive.html
 */
import Vue from 'vue'

// 自动获取焦点
Vue.directive('focus', {
  // 指令第一次绑定到元素时调用
  bind: function(el) {
    el.querySelector('input').focus()
  },
  // 被绑定元素插入父元素时调用
  inserted: function(el) {
    el.querySelector('input').focus()
  },
  // 所有组件的 VNode 更新是调用
  update: function() {},
  // 指令所在组件的 VNode 及其子 VNode 全都更新时调用
  componentUpdated: function() {},
  // 指令与元素解绑是调用
  unbind: function() {}
})

//自动获取时间戳，时间戳转换的方法
let returnDate = function(el, arg, value) {
  if (!value) {
    value = new Date().getTime()
  }
  let date = new Date(value)
  // 年
  let year = date.getFullYear()
  // 月
  let month = date.getMonth() + 1
  if (month < 10) month = '0' + String(month)
  // 日
  let day = date.getDate()
  if (day < 10) day = '0' + String(day)
  // 时
  let h = date.getHours()
  if (h < 10) h = '0' + String(h)
  // 分
  let min = date.getMinutes()
  if (min < 10) min = '0' + String(min)
  // 秒
  let s = date.getSeconds()
  if (s < 10) s = '0' + String(s)

  switch (arg) {
    case 'w':
    case 'W':
      let weeks = ['日', '一', '二', '三', '四', '五', '六']
      // 星期几
      let weekIndex = date.getDay()
      el.innerHTML = '星期' + weeks[weekIndex]
      break
    case 'yyyy-mm-dd&nbsph:m:s':
    case 'YYYY-MM-DD&nbspH:M:S':
      el.innerHTML =
        year + '-' + month + '-' + day + ' ' + h + ':' + min + ':' + s
      break
    case 'yyyy-mm-dd&nbsph:m':
    case 'YYYY-MM-DD&nbspH:M':
      el.innerHTML = year + '-' + month + '-' + day + ' ' + h + ':' + min
      break
    case 'yyyy-mm-dd':
    case 'YYYY-MM-DD':
      el.innerHTML = year + '-' + month + '-' + day
      break
    case 'yyyy#mm#dd#':
    case 'YYYY#MM#DD#':
      el.innerHTML = year + '年' + month + '月' + day + '日'
      break
    case 'yyyy-mm':
    case 'YYYY-MM':
      el.innerHTML = year + '-' + month
      break
    case 'mm-dd':
    case 'MM-DD':
      el.innerHTML = month + '-' + day
      break
    case 'yyyy':
    case 'YYYY':
      el.innerHTML = year
      break
    case 'yy':
    case 'YY':
      el.innerHTML = String(year).substring(2)
      break
    case 'mm':
    case 'MM':
      el.innerHTML = month
      break
    case 'dd':
    case 'DD':
      el.innerHTML = day
      break
    case 'h:m:s':
    case 'H:M:S':
      el.innerHTML = h + ':' + min + ':' + s
      break
    case 'h:m':
    case 'H:M':
      el.innerHTML = h + ':' + min
      break
    case 'm:s':
    case 'M:S':
      el.innerHTML = min + ':' + s
      break
    case 'h':
    case 'H':
      el.innerHTML = h
      break
    case 'm':
    case 'M':
      el.innerHTML = min
      break
    case 's':
    case 'S':
      el.innerHTML = s
      break
    default:
      el.innerHTML = value
  }
}

// 转换时间格式
Vue.directive('timeNumber', {
  inserted: function(el, binding) {
    // console.log(el, binding.arg, binding.value)

    if (binding.modifiers.refresh) {
      returnDate(el, binding.arg, binding.value)

      setInterval(function() {
        binding.value = new Date().getTime()

        returnDate(el, binding.arg, binding.value)
      }, 1000)
    } else {
      returnDate(el, binding.arg, binding.value)
    }
  },
  update: function(el, binding) {
    if (binding.modifiers.refresh) {
      returnDate(el, binding.arg, binding.value)

      setInterval(function() {
        binding.value = new Date().getTime()

        returnDate(el, binding.arg, binding.value)
      }, 1000)
    } else {
      returnDate(el, binding.arg, binding.value)
    }
  }
})

//--------------------------------------
// 另一种时间转换 eg:12394934934934-->多少分钟前||刚刚||多少小时之前
var Time = {
  //获取当前时间戳
  getUnix: function() {
    var date = new Date()
    return date.getTime()
  },
  //获取今天0点0分0秒的时间戳
  getTodayUnix: function() {
    var date = new Date()
    date.setHours(0)
    date.setMinutes(0)
    date.setSeconds(0)
    date.setMilliseconds(0)
    return date.getTime()
  },
  //获取今年1月1日0点0分0秒的时间戳
  getYearUnix: function() {
    var date = new Date()
    date.setMonth(0)
    date.setDate(1)
    date.setHours(0)
    date.setMinutes(0)
    date.setSeconds(0)
    date.setMilliseconds(0)
    return date.getTime()
  },
  //获取标准年月日
  getLastDate: function(time) {
    var date = new Date(time)
    var month =
      date.getMonth() + 1 < 10
        ? '0' + (date.getMonth() + 1)
        : date.getMonth() + 1
    var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
    return date.getFullYear() + '-' + month + '-' + day
  },
  getFormatTime: function(timestamp) {
    var now = this.getUnix() //当前时间戳
    var today = this.getTodayUnix() //今天0点的时间戳
    var year = this.getYearUnix() //今年0点的时间戳
    var timer = (now - timestamp) / 1000 //转换为秒级时间戳

    var tip = ''
    if (timer <= 0) {
      tip = '刚刚'
    } else if (Math.floor(timer / 60) <= 0) {
      tip = '刚刚'
    } else if (timer < 3600) {
      tip = Math.floor(timer / 60) + '分钟前'
    } else if (timer >= 3600 && timestamp - today >= 0) {
      tip = Math.floor(timer / 3600) + '小时前'
    } else if (timer / 86400 <= 31) {
      tip = Math.ceil(timer / 86400) + '天前'
    } else {
      //在某年某月某日
      tip = this.getLastDate(timestamp)
    }
    return tip
  }
}

Vue.directive('time', {
  bind: function(el, binding) {
    // console.log(el)
    el.innerHTML = Time.getFormatTime(binding.value)
    el.timeOut = setInterval(() => {
      el.innerHTML = Time.getFormatTime(binding.value)
    }, 60000)
  },
  unbind: function(el) {
    clearInterval(el.timeOut)
    delete el.timeOut
  }
})

//代码 替换
let codeTypeReplace = function(val) {
  return val
    .replace(/&amp;/g, '&')
    .replace(/&nbsp;/g, ' ')
    .replace(/&lt;/g, '<')
    .replace(/&amp;lt;/g, '<')
    .replace(/&gt;/g, '>')
    .replace(/&amp;gt;/g, '>')
    .replace(/&quot;/g, '"')
    .replace(/&#x2F;/g, '/')
    .replace(/&#x27;/g, "'")
    .replace(/&#x20;/g, ' ')
    .replace(/&#123;/g, '{')
    .replace(/&#125;/g, '}')
    .replace(/&#39;/g, "'")
}

// 特殊字符转换、删除
Vue.directive('code', {
  inserted: function(el, binding) {
    let val = codeTypeReplace(binding.value)

    if (binding.modifiers.del) {
      val = val.replace('[', '').replace(']', '')
    }

    el.innerHTML = val
  },
  update: function(el, binding) {
    let val = codeTypeReplace(binding.value)

    if (binding.modifiers.del) {
      val = val.replace('[', '').replace(']', '')
    }

    el.innerHTML = val
  }
})

// 添加 class
/**
 * 如果你只是想添加一个类名 [class], 而不在乎新类名插入到 classList 集合中的什么位置, 推荐你使用 :class 即可
 * 该方法 [v-pushClass] 会将新类名强制追加到 classList 集合的最后
 */
Vue.directive('pushClass', {
  bind: function(el, binding) {
    el.classList = el.classList + ' ' + binding.value
  }
})

// 元素绑定值异常时清空
Vue.directive('noHtml', {
  bind: function(el, binding) {
    if (
      binding.value != 'null' &&
      binding.value != null &&
      binding.value != '' &&
      binding.value != undefined &&
      binding.value != 'undefined'
    ) {
      el.innerHTML = ''
    }
  }
})
// 不重复随机 id
const randomID = str => {
  let id = str + String(Math.random() * 10000000000000000000).substr(0, 5)
  if (!document.getElementById(id)) {
    return id
  } else {
    randomID()
  }
}

// 渲染折叠面板
const renderFoldBox = (binding, id, html) => {
  if (binding.value.currentType == 'fold') {
    new Vue({
      el: '#' + id,
      render: function (createElement) {
        return createElement(
          'span',
          {
            attrs: { id },
            style:
              'width: calc(100% - 70px); float: left;display: inline-block;font-size: 14px;color: #666;line-height: 28px; position: relative; top: -5px;'
          },
          [
            createElement('div', {
              style:
                'height: ' + binding.value.maxHeigth + 'px; overflow: hidden',
              domProps: { innerHTML: html }
            }),
            createElement('span', {
              style: 'color: #5D6AD3; cursor: pointer;',
              on: {
                click: () => {
                  binding.value.currentType = 'open'
                  renderFoldBox(binding, id, html)
                }
              },
              domProps: { innerHTML: binding.value.openText }
            })
          ]
        )
      }
    })
  } else if (binding.value.currentType == 'open') {
    new Vue({
      el: '#' + id,
      render: function (createElement) {
        return createElement(
          'span',
          {
            attrs: { id },
            style:
              'width: calc(100% - 70px); float: left;display: inline-block;font-size: 14px;color: #666;line-height: 28px; position: relative; top: -5px;'
          },
          [
            createElement('div', {
              domProps: { innerHTML: html }
            }),
            createElement('span', {
              style: 'color: #5D6AD3; cursor: pointer;',
              on: {
                click: () => {
                  binding.value.currentType = 'fold'
                  renderFoldBox(binding, id, html)
                }
              },
              domProps: { innerHTML: binding.value.foldText }
            })
          ]
        )
      }
    })
  }
}

// 面板折叠
Vue.directive('fold', {
  inserted: function (el, binding) {
    // 添加随机 id
    let id = randomID('prevent')
    el.id = id
    let [style, html] = [el.style, el.innerHTML]

    // 折叠、收起默认文字
    if (!binding.value.openText) {
      binding.value.openText = '展开'
    }
    if (!binding.value.foldText) {
      binding.value.foldText = '收起'
    }
    let height = el.offsetHeight

    // 最大高度拦截
    if (height > binding.value.maxHeigth) {
      renderFoldBox(binding, id, html)
    }
  },
  updated: function (el, binding) {
    // 添加随机 id
    let id = randomID('prevent')
    el.id = id
    let [style, html] = [el.style, el.innerHTML]

    // 折叠、收起默认文字
    if (!binding.value.openText) {
      binding.value.openText = '展开'
    }
    if (!binding.value.foldText) {
      binding.value.foldText = '收起'
    }
    let height = el.offsetHeight

    // 最大高度拦截
    if (height > binding.value.maxHeigth) {
      renderFoldBox(binding, id, html)
    }
  }
})
